package com.icekrvams.air.installreferrer

import android.content.Context
import android.os.Bundle
import android.text.TextUtils
import com.android.installreferrer.api.InstallReferrerClient
import com.android.installreferrer.api.InstallReferrerStateListener
import com.icekrvams.air.mmkv

object InstallReferrerTool {

    private const val PREFS_AUDIENCES_TYPE = "com.install.referrer.audiences.type.version2"
    private const val UTM_SOURCE = "utm_source"
    private const val UTM_MEDIUM = "utm_medium"

    private const val AUDIENCES_TYPE_MY_GP_INSTALL_ORGANIC = 10005
    private const val AUDIENCES_TYPE_MY_GP_INSTALL_THIRD_PART = 10006
    private const val AUDIENCES_TYPE_MY_NGP_INSTALL = 10007
    private const val AUDIENCES_TYPE_CRACK_GP_INSTALL = 10008
    private const val AUDIENCES_TYPE_CRACK_NGP_INSTALL = 10009

    // -1 设备上从没有安装过
    private const val FETCH_AUDIENCES_STATE_NONE = -1

    // 0 已经获取过渠道
    private const val FETCH_AUDIENCES_STATE_SUCCESS = 0

    private const val INSTALL_ALL = "install_all"
    private const val INSTALL_SUM = "install_sum"
    private const val KEY_RELEASE_CHANNEL = "release_channel"
    private const val KEY_PACKAGE_NAME = "package_name"
    private const val MY_GP_INSTALL_ORGANIC = "my_gp_install_organic"
    private const val MY_GP_INSTALL_THIRD_PART = "my_gp_install_third_part"
    private const val MY_NGP_INSTALL = "my_ngp_install"
    private const val CRACK_GP_INSTALL = "crack_gp_install"
    private const val CRACK_NGP_INSTALL = "crack_ngp_install"
    private const val PREF_HAS_FETCHED_REFERRER = "has_fetched_referrer_version2"
    private const val PREF_HAS_ALL_INSTALL_RECORDED = "has_all_install_recorded"

    @JvmOverloads
    fun fetchReferrer(
        context: Context,
        installReferrerCollector: InstallReferrerCollector,
        showSignatureLog: Boolean = false
    ) {
        val hasAllInstallRecorded = mmkv.getBoolean(PREF_HAS_ALL_INSTALL_RECORDED, false)
        if (!hasAllInstallRecorded) {
            installReferrerCollector.onCollectEvent(INSTALL_ALL)
            mmkv.encode(PREF_HAS_ALL_INSTALL_RECORDED, true)
        }

        val hasFetchedReferrer =
            mmkv.getInt(PREF_HAS_FETCHED_REFERRER, FETCH_AUDIENCES_STATE_NONE)
        if (hasFetchedReferrer == FETCH_AUDIENCES_STATE_SUCCESS) return

        val signature = installReferrerCollector.onGetSignature()
        if (!PiracyChecker.verifyAppSignature(context, signature, showSignatureLog)) {
            // 应用被二次签名打包。
            if (PiracyChecker.verifyInstaller(context)) {
                // 应用被二次签名打包且发布在PlayStore上。
                logChannelEvent(installReferrerCollector, CRACK_GP_INSTALL, context.packageName)
                mmkv.encode(PREFS_AUDIENCES_TYPE, AUDIENCES_TYPE_CRACK_GP_INSTALL)
            } else {
                // 应用被二次签名打包且发布在其他渠道上。
                logChannelEvent(
                    installReferrerCollector,
                    CRACK_NGP_INSTALL,
                    context.packageName
                )
                mmkv.encode(PREFS_AUDIENCES_TYPE, AUDIENCES_TYPE_CRACK_NGP_INSTALL)
            }
            mmkv.encode(PREF_HAS_FETCHED_REFERRER, FETCH_AUDIENCES_STATE_SUCCESS)
            return
        }
        if (!PiracyChecker.verifyInstaller(context)) {
            // 应用没被二次签名打包且发布在其他渠道。
            logChannelEvent(installReferrerCollector, MY_NGP_INSTALL)
            mmkv.encode(PREFS_AUDIENCES_TYPE, AUDIENCES_TYPE_MY_NGP_INSTALL)
            mmkv.encode(PREF_HAS_FETCHED_REFERRER, FETCH_AUDIENCES_STATE_SUCCESS)
            return
        }
        try {
            val referrerClient = InstallReferrerClient.newBuilder(context).build()
            referrerClient.startConnection(object : InstallReferrerStateListener {
                override fun onInstallReferrerSetupFinished(responseCode: Int) {
                    when (responseCode) {
                        InstallReferrerClient.InstallReferrerResponse.OK -> {
                            var referrerUrl = ""
                            var referrerClickTimestampSeconds = -1L
                            try {
                                referrerClient.installReferrer.apply {
                                    referrerUrl = installReferrer
                                    referrerClickTimestampSeconds =
                                        getReferrerClickTimestampSeconds()
                                }
                            } catch (e: Exception) {
                                referrerUrl = ""
                            } finally {
                                parseReferrerUrl(
                                    installReferrerCollector,
                                    referrerUrl,
                                    referrerClickTimestampSeconds
                                )
                                referrerClient.endConnection()
                            }
                        }
                        InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED ->
                            noReferrerTrack(installReferrerCollector, "feature_not_supported")
                        InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE ->
                            noReferrerTrack(installReferrerCollector, "service_unavailable")
                    }
                }

                override fun onInstallReferrerServiceDisconnected() {
                }
            })
        } catch (e: Exception) {
            installReferrerCollector.onCollectEvent("startConnection_error")
            logChannelEvent(installReferrerCollector, MY_GP_INSTALL_THIRD_PART)
        }
    }

    private fun logChannelEvent(
        installReferrerCollector: InstallReferrerCollector,
        channel: String,
        packageName: String? = null
    ) {
        val bundle = Bundle()
        bundle.putString(KEY_RELEASE_CHANNEL, channel)
        if (!packageName.isNullOrEmpty()) {
            bundle.putString(KEY_PACKAGE_NAME, packageName)
        }
        installReferrerCollector.onCollectEvent(INSTALL_SUM, bundle)
    }

    private fun parseReferrerUrl(
        installReferrerCollector: InstallReferrerCollector,
        referrer: String,
        timeStamp: Long
    ) {
        if (TextUtils.isEmpty(referrer)) {
            noReferrerTrack(installReferrerCollector)
            return
        }
        val bundle = buildReferrerBundle(referrer)
        if (bundle == null) {
            noReferrerTrack(installReferrerCollector)
            return
        }
        bundle.putString("bundle", bundle2string(bundle))
        bundle.putString("timeStamp", timeStamp.toString() + "")
        installReferrerCollector.onCollectEvent("install_with_referrer", bundle)
        trackChannels(installReferrerCollector, bundle)

        mmkv.encode(PREF_HAS_FETCHED_REFERRER, FETCH_AUDIENCES_STATE_SUCCESS)
    }

    private fun noReferrerTrack(
        installReferrerCollector: InstallReferrerCollector,
        msg: String? = null
    ) {
        logChannelEvent(installReferrerCollector, MY_GP_INSTALL_THIRD_PART)
        if (!TextUtils.isEmpty(msg)) {
            val bundle = Bundle()
            bundle.putString("msg", msg)
            installReferrerCollector.onCollectEvent("install_no_referrer", bundle)
        } else {
            installReferrerCollector.onCollectEvent("install_no_referrer")
        }

        // 因为防止install_sum数据重复，所以这个地方也记录为FETCH_AUDIENCES_STATE_SUCCESS    author: SheWenBiao
        mmkv.encode(PREF_HAS_FETCHED_REFERRER, FETCH_AUDIENCES_STATE_SUCCESS)
    }

    private fun buildReferrerBundle(referrer: String): Bundle? {
        var bundle: Bundle? = null
        val referrerArray = referrer.split("&".toRegex()).toTypedArray()
        if (referrerArray.isNotEmpty()) {
            bundle = Bundle()
            for (ref in referrerArray) {
                if (!TextUtils.isEmpty(ref)) {
                    val utmArray = ref.split("=".toRegex()).toTypedArray()
                    if (utmArray.size == 2) {
                        bundle.putString(utmArray[0], utmArray[1])
                    }
                }
            }
        }
        return bundle
    }

    private fun bundle2string(bundle: Bundle?): String? {
        if (bundle == null) {
            return null
        }
        val string = StringBuilder("Bundle{")
        for (key in bundle.keySet()) {
            string.append(" ").append(key).append(" => ").append(bundle[key]).append(";")
        }
        string.append(" }Bundle")
        return string.toString()
    }

    /**
     * region >>> 渠道划分
     */
    private fun trackChannels(
        installReferrerCollector: InstallReferrerCollector,
        bundle: Bundle
    ) {
        // record audiences type
        val utmSource = bundle.getString(UTM_SOURCE)
        val utmMedium = bundle.getString(UTM_MEDIUM)
        if (isGpOrganic(utmSource, utmMedium)) {
            logChannelEvent(installReferrerCollector, MY_GP_INSTALL_ORGANIC, null)
            mmkv.encode(PREFS_AUDIENCES_TYPE, AUDIENCES_TYPE_MY_GP_INSTALL_ORGANIC)
        } else {
            logChannelEvent(installReferrerCollector, MY_GP_INSTALL_THIRD_PART, null)
            mmkv.encode(PREFS_AUDIENCES_TYPE, AUDIENCES_TYPE_MY_GP_INSTALL_THIRD_PART)
        }
    }

    // utm_source = google-play, utm_medium = organic
    private fun isGpOrganic(utm_source: String?, utm_medium: String?): Boolean {
        return TextUtils.equals(utm_source, "google-play") && TextUtils.equals(
            utm_medium,
            "organic"
        )
    }
}